package dao.jdbc.SqlServer;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.Calendar;

import dao.intefaces.InterfaceInformesDAO;

public class InformeDAO implements InterfaceInformesDAO{

	private static InformeDAO instancia = null;
	
	public static InformeDAO getInstancia(){
		if (instancia == null){
			instancia = new InformeDAO();
		}
		return instancia;
	}

	@SuppressWarnings("deprecation")
	private int getCantidadFilasInformeFacturacion(Calendar fechaInicio, Calendar fechaFin)
	{
		int cantFilas = 0;
		PreparedStatement stmt = null;
		ResultSet resultSet = null;
		try{
			Connection conexion = DataSource.obtenerConexion();
			String query = 	"select distinct f.nroFactura, f.fecha, c.cuit as 'CUIT', p.nroPresupuesto, aux.total as 'totalFactura' " +
							"from factura f inner join precioItem item on item.nroFactura = f.nroFactura " +
							"inner join presupuesto p on p.nroPresupuesto = item.nroPresupuesto " +
							"inner join cliente c on p.cuit = c.cuit " +
							"inner join	(select item.nroFactura, sum (item.precio * item.cantidad) as total " +
										"from factura f inner join precioItem item on item.nroFactura = f.nroFactura " +
										"group by item.nroFactura) aux on aux.nroFactura = f.nroFactura " +
							"where f.fecha between '" + fechaInicio.getTime().toLocaleString() + "' and '" + fechaFin.getTime().toLocaleString() + "';";
			stmt = conexion.prepareStatement(query);
			resultSet = stmt.executeQuery();
			while (resultSet.next()){
				cantFilas++;
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			DataSource.cerrarConexion(resultSet, stmt);
		}
		return cantFilas;
	}
	
	@SuppressWarnings({ "deprecation" })
	public String[][] getInformeFacturacion(Calendar fechaInicio, Calendar fechaFin) 
	{
		String[][] resultadoInforme = new String[getCantidadFilasInformeFacturacion(fechaInicio, fechaFin)][5];
		PreparedStatement stmt = null;
		ResultSet resultSet = null;
		try{
			Connection conexion = DataSource.obtenerConexion();
			String query = 	"select distinct f.nroFactura, f.fecha, c.cuit as 'CUIT', p.nroPresupuesto, aux.total as 'totalFactura' " +
							"from factura f inner join precioItem item on item.nroFactura = f.nroFactura " +
							"inner join presupuesto p on p.nroPresupuesto = item.nroPresupuesto " +
							"inner join cliente c on p.cuit = c.cuit " +
							"inner join	(select item.nroFactura, sum (item.precio * item.cantidad) as total " +
										"from factura f inner join precioItem item on item.nroFactura = f.nroFactura " +
										"group by item.nroFactura) aux on aux.nroFactura = f.nroFactura " +
							"where f.fecha between '" + fechaInicio.getTime().toLocaleString() + "' and '" + fechaFin.getTime().toLocaleString() + "';";
			stmt = conexion.prepareStatement(query);
			resultSet = stmt.executeQuery();
			// Una vez realizado el query pueblo la matriz
			int fila = 0;
			while (resultSet.next()){
				resultadoInforme[fila][0] = String.valueOf(resultSet.getInt("nroFactura"));
				Timestamp fecha = resultSet.getTimestamp("fecha");
				resultadoInforme[fila][1] = fecha.getDay() + "/" + (fecha.getMonth()+1) + "/" + (fecha.getYear()+1900);
				resultadoInforme[fila][3] = resultSet.getString("CUIT");
				resultadoInforme[fila][4] = String.valueOf(resultSet.getInt("nroPresupuesto"));
				resultadoInforme[fila][2] = String.valueOf(resultSet.getInt("totalFactura"));
				fila++;
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			DataSource.cerrarConexion(resultSet, stmt);
		}
		return resultadoInforme;
	}

	@SuppressWarnings("deprecation")
	@Override
	public float getTotalFacturacion(Calendar fechaInicio, Calendar fechaFin) {
		// TODO Auto-generated method stub
		float totalFacturado = 0;
		PreparedStatement stmt = null;
		ResultSet resultSet = null;
		try{
			Connection conexion = DataSource.obtenerConexion();
			String subquery = "select distinct f.nroFactura, f.fecha, c.cuit as 'CUIT', p.nroPresupuesto, aux.total as 'totalFacturado' " +
					"from factura f inner join precioItem item on item.nroFactura = f.nroFactura " +
					"inner join presupuesto p on p.nroPresupuesto = item.nroPresupuesto " +
					"inner join cliente c on p.cuit = c.cuit " +
					"inner join	(select item.nroFactura, sum (item.precio * item.cantidad) as total " +
								"from factura f inner join precioItem item on item.nroFactura = f.nroFactura " +
								"group by item.nroFactura) aux on aux.nroFactura = f.nroFactura " +
					"where f.fecha between '" + fechaInicio.getTime().toLocaleString() + "' and '" + fechaFin.getTime().toLocaleString() + "'";
			String query = 	"select sum(totalFacturado) as 'total' " +
							"from (" + subquery + ") aux;";
			stmt = conexion.prepareStatement(query);
			resultSet = stmt.executeQuery();
			// Una vez realizado el query pueblo la matriz
			while (resultSet.next()){
				totalFacturado = resultSet.getFloat("total");	
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			DataSource.cerrarConexion(resultSet, stmt);
		}
		return totalFacturado;
	}

	@SuppressWarnings("deprecation")
	@Override
	public String[][] getInformeFacturacion(Calendar fechaInicio,
			Calendar fechaFin, String CUIT) {
		String[][] resultadoInforme = new String[getCantidadFilasInformeFacturacion(fechaInicio, fechaFin)][4];
		PreparedStatement stmt = null;
		ResultSet resultSet = null;
		try{
			Connection conexion = DataSource.obtenerConexion();
			String query = 	"select distinct f.nroFactura, f.fecha, c.cuit as 'CUIT', p.nroPresupuesto, aux.total as 'totalFactura' " +
							"from factura f inner join precioItem item on item.nroFactura = f.nroFactura " +
							"inner join presupuesto p on p.nroPresupuesto = item.nroPresupuesto " +
							"inner join cliente c on p.cuit = c.cuit " +
							"inner join	(select item.nroFactura, sum (item.precio * item.cantidad) as total " +
										"from factura f inner join precioItem item on item.nroFactura = f.nroFactura " +
										"group by item.nroFactura) aux on aux.nroFactura = f.nroFactura " +
							"where f.fecha between '" + fechaInicio.getTime().toLocaleString() + "' and '" + fechaFin.getTime().toLocaleString() + "' " +
									"and c.CUIT = '" + CUIT + "';";
			stmt = conexion.prepareStatement(query);
			resultSet = stmt.executeQuery();
			// Una vez realizado el query pueblo la matriz
			int fila = 0;
			while (resultSet.next()){
				resultadoInforme[fila][0] = String.valueOf(resultSet.getInt("nroFactura"));
				Timestamp fecha = resultSet.getTimestamp("fecha");
				resultadoInforme[fila][1] = fecha.getDay() + "/" + (fecha.getMonth()+1) + "/" + (fecha.getYear()+1900);
//				resultadoInforme[fila][3] = resultSet.getString("CUIT");
				resultadoInforme[fila][3] = String.valueOf(resultSet.getInt("nroPresupuesto"));
				resultadoInforme[fila][2] = String.valueOf(resultSet.getInt("totalFactura"));
				fila++;
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			DataSource.cerrarConexion(resultSet, stmt);
		}
		return resultadoInforme;
	}

	@SuppressWarnings("deprecation")
	@Override
	public float getTotalFacturacion(Calendar fechaInicio, Calendar fechaFin, String CUIT) {
		// TODO Auto-generated method stub
		float totalFacturado = 0;
		PreparedStatement stmt = null;
		ResultSet resultSet = null;
		try{
			Connection conexion = DataSource.obtenerConexion();
			String subquery = "select distinct f.nroFactura, f.fecha, c.cuit as 'CUIT', p.nroPresupuesto, aux.total as 'totalFacturado' " +
					"from factura f inner join precioItem item on item.nroFactura = f.nroFactura " +
					"inner join presupuesto p on p.nroPresupuesto = item.nroPresupuesto " +
					"inner join cliente c on p.cuit = c.cuit " +
					"inner join	(select item.nroFactura, sum (item.precio * item.cantidad) as total " +
								"from factura f inner join precioItem item on item.nroFactura = f.nroFactura " +
								"group by item.nroFactura) aux on aux.nroFactura = f.nroFactura " +
					"where f.fecha between '" + fechaInicio.getTime().toLocaleString() + "' and '" + fechaFin.getTime().toLocaleString() + "' " +
							"and c.cuit = '" + CUIT + "'";
					
			String query = 	"select sum(totalFacturado) as 'total' " +
							"from (" + subquery + ") aux;";
			stmt = conexion.prepareStatement(query);
			resultSet = stmt.executeQuery();
			// Una vez realizado el query pueblo la matriz
			while (resultSet.next()){
				totalFacturado = resultSet.getFloat("total");	
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			DataSource.cerrarConexion(resultSet, stmt);
		}
		return totalFacturado;
	}
	
	@SuppressWarnings("deprecation")
	private int getCantidadFilasInformeTipoServicio(Calendar fechaInicio, Calendar fechaFin)
	{
		int cantFilas = 0;
		PreparedStatement stmt = null;
		ResultSet resultSet = null;
		try{
			Connection conexion = DataSource.obtenerConexion();
			String query = 	"select t.nroTipoServicio, t.descripcion, count(t.nroTipoServicio) as 'cantidadRealizados' " +
							"from precioItem p inner join factura f on f.nroFactura = p.nroFactura " +
							"inner join tipoServicio t on t.nroTipoServicio = p.nroTipoServicio " + 
							"where f.fecha between '" + fechaInicio.getTime().toLocaleString() + "' and '" + fechaFin.getTime().toLocaleString() + "' " +
							"group by t.nroTipoServicio, t.descripcion;";
			stmt = conexion.prepareStatement(query);
			resultSet = stmt.executeQuery();
			while (resultSet.next()){
				cantFilas++;
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			DataSource.cerrarConexion(resultSet, stmt);
		}
		return cantFilas;
	}

	@SuppressWarnings("deprecation")
	@Override
	public String[][] getInformeTipoServicio(Calendar fechaInicio, Calendar fechaFin) {
		// TODO Auto-generated method stub
        String[][] resultadoInforme = new String[getCantidadFilasInformeTipoServicio(fechaInicio, fechaFin)][2];
        PreparedStatement stmt = null;
        ResultSet resultSet = null;
        try{
                Connection conexion = DataSource.obtenerConexion();
                String query = "select t.nroTipoServicio, t.descripcion, count(t.nroTipoServicio) as 'cantidadRealizados' " +
                                "from precioItem p inner join factura f on f.nroFactura = p.nroFactura " +
                                "inner join tipoServicio t on t.nroTipoServicio = p.nroTipoServicio " + 
                                "where f.fecha between '" + fechaInicio.getTime().toLocaleString() + "' and '" + fechaFin.getTime().toLocaleString() + "' " +
                                "group by t.nroTipoServicio, t.descripcion;";
                
                stmt = conexion.prepareStatement(query);
                resultSet = stmt.executeQuery();

                // Una vez realizado el query pueblo la matriz
                int filaActual = 0;
                while (resultSet.next()){
                        resultadoInforme[filaActual][0] = resultSet.getString("descripcion");
                        resultadoInforme[filaActual][1] = String.valueOf(resultSet.getInt("cantidadRealizados"));
                        filaActual++;
                }
        }catch(Exception e){
                e.printStackTrace();
        }finally{
                DataSource.cerrarConexion(resultSet, stmt);
        }
        return resultadoInforme;
	}

	@SuppressWarnings("deprecation")
	@Override
	public String[][] getInformeEstadosPresupuestos(Calendar fechaInicio, Calendar fechaFin) {
		String[][] resultadoInforme = new String[getCantidadFilasInformeEstadosPresupuestos(fechaInicio, fechaFin)][2];
		PreparedStatement stmt = null;
		ResultSet resultSet = null;
		try{
			Connection conexion = DataSource.obtenerConexion();
			String query = "select ep.descripcion, count(*) as 'cantidad' " +
					"from presupuesto p inner join estadoPresupuesto ep on p.nroEstado = ep.nroEstado " +
					"where p.fechaEmision between '" + fechaInicio.getTime().toLocaleString() + "' and '" + fechaFin.getTime().toLocaleString() + "' " +
					"group by ep.nroEstado, ep.descripcion;";
			
			stmt = conexion.prepareStatement(query);
			resultSet = stmt.executeQuery();

			// Una vez realizado el query pueblo la matriz
			int filaActual = 0;
			while (resultSet.next()){
				resultadoInforme[filaActual][0] = resultSet.getString("descripcion");
				resultadoInforme[filaActual][1] = String.valueOf(resultSet.getInt("cantidad"));
				filaActual++;
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			DataSource.cerrarConexion(resultSet, stmt);
		}
		return resultadoInforme;
	}
	
	private int getCantidadFilasInformeEstadosPresupuestos(Calendar fechaInicio, Calendar fechaFin)
	{
		int cantFilas = 0;
		PreparedStatement stmt = null;
		ResultSet resultSet = null;
		try{
			Connection conexion = DataSource.obtenerConexion();
			@SuppressWarnings("deprecation")
			String query = "select ep.descripcion, count(*) as 'cantidad' " +
					"from presupuesto p inner join estadoPresupuesto ep on p.nroEstado = ep.nroEstado " +
					"where p.fechaEmision between '" + fechaInicio.getTime().toLocaleString() + "' and '" + fechaFin.getTime().toLocaleString() + "' " +
					"group by ep.nroEstado, ep.descripcion;";
			
			stmt = conexion.prepareStatement(query);
			resultSet = stmt.executeQuery();

			// Una vez realizado el query pueblo la matriz
			while (resultSet.next()){
				cantFilas++;
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			DataSource.cerrarConexion(resultSet, stmt);
		}
		return cantFilas;
	}

	@SuppressWarnings("deprecation")
	@Override
	public String[][] getFacturacionXMeses(Calendar fechaInicio,
			Calendar fechaFin) {
		// TODO Auto-generated method stub
		String[][] resultadoInforme = new String[getCantidadFilasInformeFacturacionXMes(fechaInicio, fechaFin)][2];
		PreparedStatement stmt = null;
		ResultSet resultSet = null;
		try{
			Connection conexion = DataSource.obtenerConexion();
			String query = 	"select datename(m, f.FECHA) + ' ' + cast(year(f.FECHA)as varchar(4)) as 'fecha', sum(p.precio*p.cantidad) as 'montoFacturado' " + 
							"from factura f inner join precioItem p on p.nroFactura = f.nroFactura " +
							"where f.fecha between '" + fechaInicio.getTime().toLocaleString() + "' and '" + fechaFin.getTime().toLocaleString() + "' " + 
							"group by datename(m, f.FECHA) + ' ' + cast(year(f.FECHA)as varchar(4)); ";
			
			stmt = conexion.prepareStatement(query);
			resultSet = stmt.executeQuery();

			// Una vez realizado el query pueblo la matriz
			int filaActual = 0;
			while (resultSet.next()){
				resultadoInforme[filaActual][0] = resultSet.getString("fecha");
				resultadoInforme[filaActual][1] = String.valueOf(resultSet.getInt("montoFacturado"));
				filaActual++;
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			DataSource.cerrarConexion(resultSet, stmt);
		}
		return resultadoInforme;
	}
	
	private int getCantidadFilasInformeFacturacionXMes(Calendar fechaInicio, Calendar fechaFin){
		int cantFilas = 0;
		PreparedStatement stmt = null;
		ResultSet resultSet = null;
		try{
			Connection conexion = DataSource.obtenerConexion();
			@SuppressWarnings("deprecation")
			String query = "select datename(m, f.FECHA) + ' ' + cast(year(f.FECHA)as varchar(4)) as 'fecha', sum(p.precio*p.cantidad) as 'montoFacturado' " + 
					"from factura f inner join precioItem p on p.nroFactura = f.nroFactura " +
					"where f.fecha between '" + fechaInicio.getTime().toLocaleString() + "' and '" + fechaFin.getTime().toLocaleString() + "' " + 
					"group by datename(m, f.FECHA) + ' ' + cast(year(f.FECHA)as varchar(4)); ";
			
			stmt = conexion.prepareStatement(query);
			resultSet = stmt.executeQuery();

			// Una vez realizado el query voy contando las filas que obtengo de resultado
			while (resultSet.next()){
				cantFilas++;
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			DataSource.cerrarConexion(resultSet, stmt);
		}
		return cantFilas;
	}
	
}
